package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysDocumentCodeRule;
import com.ruoyi.system.mapper.SysDocumentCodeRuleMapper;
import com.ruoyi.system.service.ISysDocumentCodeRuleService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 单据编码规则维护
 *
 * @author wn
 * @date 2024/8/14
 */
@Service
public class SysDocumentCodeRuleServiceImpl extends ServiceImpl<SysDocumentCodeRuleMapper, SysDocumentCodeRule> implements ISysDocumentCodeRuleService {

    @Resource
    private RedissonClient redissonClient;


    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysDocumentCodeRule> getPageList(SysDocumentCodeRule documentRuleRequest) {
        String dataScope = "";
        Map<String, Object> params = documentRuleRequest.getParams();
        if (StringUtils.isNotEmpty(params)){
            dataScope = params.get("dataScope").toString();
        }
        LambdaQueryWrapper<SysDocumentCodeRule> wrapper = Wrappers.lambdaQuery(SysDocumentCodeRule.class);
        wrapper.like(StringUtils.isNotEmpty(documentRuleRequest.getDocumentPrefixCode()), SysDocumentCodeRule::getDocumentPrefixCode, documentRuleRequest.getDocumentPrefixCode());
        wrapper.like(StringUtils.isNotEmpty(documentRuleRequest.getDocumentCode()), SysDocumentCodeRule::getDocumentCode, documentRuleRequest.getDocumentCode());
        wrapper.like(StringUtils.isNotNull(documentRuleRequest.getDocumentName()), SysDocumentCodeRule::getDocumentName, documentRuleRequest.getDocumentName());
        wrapper.orderByDesc(SysDocumentCodeRule::getCreateTime);
        List<SysDocumentCodeRule> records = this.list(wrapper);
        return records;
    }

    @Override
    public void saveDocumentRule(SysDocumentCodeRule documentRuleRequest) {
        this.save(documentRuleRequest);
    }

    @Override
    public void updateDocumentRule(SysDocumentCodeRule documentRuleRequest) {
        this.updateById(documentRuleRequest);
    }


    @Override
    public void deleteCurrency(String ids) {
        String[] split = ids.split(",");
        List list = Arrays.asList(split);
        this.removeByIds(list);
    }

    @Override
    public SysDocumentCodeRule getByCode(String code) {
        return this.getOne(Wrappers.lambdaQuery(SysDocumentCodeRule.class)
                .eq(SysDocumentCodeRule::getDocumentCode, code));
    }
    @Override
    public List<SysDocumentCodeRule> getSelectCondition() {
        return this.baseMapper.getSelectCondition();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> getDocumentCodeByCode(String code, Integer length) {
        RLock lock = redissonClient.getLock(code.intern());
        lock.lock();
        List<String> codes = new ArrayList<>();
        //synchronized (code.intern()) {
        try{
            if(null == length || length < 1){
                length = 1;
            }

            SysDocumentCodeRule documentRule = this.getOne(Wrappers.lambdaQuery(SysDocumentCodeRule.class).eq(SysDocumentCodeRule::getDocumentCode, code));
            if(documentRule == null){
                return null;
            }
            String prefixCode = documentRule.getDocumentPrefixCode();
            Integer documentNumLength = documentRule.getDocumentNumLength();
            Integer initialValue = documentRule.getInitialValue();
            Integer currentValue = documentRule.getCurrentValue() == null ? (initialValue-1) : documentRule.getCurrentValue();
            String connector = documentRule.getConnector();
            String dateType = documentRule.getDateType();
            String formatDate = "";
            String nowSerialNo = "";
            //流水号需要拼接 日期字符串
            if (StringUtils.isNotEmpty(dateType)) {
                formatDate = DateUtils.format(new Date(), dateType);
                String lastSerialNo = documentRule.getLastSerialNo();
                // 如果跟上次日期不同，重置流水号 //如果上次流水号是空的，说明是第一次取，直接拼接日期
                if(StringUtils.isNotEmpty(lastSerialNo) && lastSerialNo.indexOf(formatDate) < 0){
                    currentValue = (initialValue-1);
                }
                formatDate = formatDate + connector;
            }
            for (int i = 0; i < length; i++) {
                currentValue += 1;
                String serialNo = String.format("%0" + documentNumLength + "d", currentValue);
                String doCode = prefixCode + connector + formatDate + serialNo;
                codes.add(doCode);
                nowSerialNo = doCode;
            }

            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("id", documentRule.getId());
            SysDocumentCodeRule c = new SysDocumentCodeRule();
            c.setCurrentValue(currentValue);
            c.setLastSerialNo(nowSerialNo);
            this.update(c, updateWrapper);

            return codes;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        return null;
    }


}
